using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;

namespace NodeCanvas
{
	public class AgentUtilities : MonoBehaviour
	{
		private class Listener
		{
			public object target;

			public List<string> messages = new List<string>();

			public Listener(object target, string message)
			{
				this.target = target;
				messages.Add(message);
			}
		}

		private List<Listener> listeners = new List<Listener>();

		private void OnAnimatorIK(int layerIndex)
		{
			Send("OnAnimatorIK", layerIndex);
		}

		private void OnAnimatorMove()
		{
			Send("OnAnimatorMove", null);
		}

		private void OnBecameInvisible()
		{
			Send("OnBecameInvisible", null);
		}

		private void OnBecameVisible()
		{
			Send("OnBecameVisible", null);
		}

		private void OnCollisionEnter(Collision collisionInfo)
		{
			Send("OnCollisionEnter", collisionInfo);
		}

		private void OnCollisionExit(Collision collisionInfo)
		{
			Send("OnCollisionExit", collisionInfo);
		}

		private void OnCollisionStay(Collision collisionInfo)
		{
			Send("OnCollisionStay", collisionInfo);
		}

		private void OnCollisionEnter2D(Collision2D collisionInfo)
		{
			Send("OnCollisionEnter2D", collisionInfo);
		}

		private void OnCollisionExit2D(Collision2D collisionInfo)
		{
			Send("OnCollisionExit2D", collisionInfo);
		}

		private void OnCollisionStay2D(Collision2D collisionInfo)
		{
			Send("OnCollisionStay2D", collisionInfo);
		}

		private void OnTriggerEnter(Collider other)
		{
			Send("OnTriggerEnter", other);
		}

		private void OnTriggerExit(Collider other)
		{
			Send("OnTriggerExit", other);
		}

		private void OnTriggerStay(Collider other)
		{
			Send("OnTriggerStay", other);
		}

		private void OnTriggerEnter2D(Collider2D other)
		{
			Send("OnTriggerEnter2D", other);
		}

		private void OnTriggerExit2D(Collider2D other)
		{
			Send("OnTriggerExit2D", other);
		}

		private void OnTriggerStay2D(Collider2D other)
		{
			Send("OnTriggerStay2D", other);
		}

		private void OnMouseDown()
		{
			Send("OnMouseDown", null);
		}

		private void OnMouseDrag()
		{
			Send("OnMouseDrag", null);
		}

		private void OnMouseEnter()
		{
			Send("OnMouseEnter", null);
		}

		private void OnMouseExit()
		{
			Send("OnMouseExit", null);
		}

		private void OnMouseOver()
		{
			Send("OnMouseOver", null);
		}

		private void OnMouseUp()
		{
			Send("OnMouseUp", null);
		}

		private void OnCustomEvent(string eventName)
		{
			Send("OnCustomEvent", eventName);
		}

		public void Listen(object target, string toMessage)
		{
			foreach (Listener listener in listeners)
			{
				if (listener.target == target)
				{
					if (!listener.messages.Contains(toMessage))
					{
						listener.messages.Add(toMessage);
					}
					return;
				}
			}
			listeners.Add(new Listener(target, toMessage));
		}

		public void Forget(object target)
		{
			foreach (Listener listener in listeners)
			{
				if (listener.target == target)
				{
					listeners.Remove(listener);
					break;
				}
			}
		}

		public void Forget(object target, string forgetMessage)
		{
			foreach (Listener listener in listeners)
			{
				if (listener.target == target)
				{
					listener.messages.Remove(forgetMessage);
					if (listener.messages.Count == 0)
					{
						listeners.Remove(listener);
					}
					break;
				}
			}
		}

		public void Send(string eventName, object arg)
		{
			foreach (Listener listener in listeners)
			{
				foreach (string message in listener.messages)
				{
					if (eventName == message && listener.target != null)
					{
						MethodInfo methodInfo = listener.target.GetType().NCGetMethod(eventName, true);
						if (methodInfo == null)
						{
							Debug.LogWarning("Method '" + eventName + "' not found on subscribed type " + listener.target.GetType().Name);
							return;
						}
						object[] parameters = ((methodInfo.GetParameters().Length != 1) ? null : new object[1] { arg });
						if (methodInfo.ReturnType == typeof(IEnumerator))
						{
							MonoManager.current.StartCoroutine((IEnumerator)methodInfo.Invoke(listener.target, parameters));
						}
						else
						{
							methodInfo.Invoke(listener.target, parameters);
						}
					}
				}
			}
		}
	}
}
